(function(b) {
	var a = {};
	a.config = {
		editable : true,
		lineHeight : 15,
		basePath : "",
		rect : {
			attr : {
				x : 10,
				y : 10,
				width : 100,
				height : 50,
				r : 5,
				fill : "90-#fff-#C0C0C0",
				stroke : "#000",
				"stroke-width" : 1
			},
			showType : "image&text",
			type : "manual",
			name : {
				text : "state",
				"font-style" : "italic"
			},
			text : {
				text : "状态",
				"font-size" : 13
			},
			margin : 5,
			props : [],
			img : {}
		},
		path : {
			attr : {
				path : {
					path : "M10 10L100 100",
					stroke : "#808080",
					fill : "none",
					"stroke-width" : 2
				},
				arrow : {
					path : "M10 10L10 10",
					stroke : "#808080",
					fill : "#808080",
					"stroke-width" : 2,
					radius : 4
				},
				fromDot : {
					width : 5,
					height : 5,
					stroke : "#fff",
					fill : "#000",
					cursor : "move",
					"stroke-width" : 2
				},
				toDot : {
					width : 5,
					height : 5,
					stroke : "#fff",
					fill : "#000",
					cursor : "move",
					"stroke-width" : 2
				},
				bigDot : {
					width : 5,
					height : 5,
					stroke : "#fff",
					fill : "#000",
					cursor : "move",
					"stroke-width" : 2
				},
				smallDot : {
					width : 5,
					height : 5,
					stroke : "#fff",
					fill : "#000",
					cursor : "move",
					"stroke-width" : 3
				}
			},
			text : {
				text : "TO {to}",
				cursor : "move",
				background : "#000"
			},
			textPos : {
				x : 0,
				y : -10
			},
			props : {
				text : {
					name : "text",
					label : "显示",
					value : ""
				},
				key : {
					name : "key",
					label : "标识",
					value : ""
				},
				code : {
					name : "code",
					label : "编码",
					value : ""
				}				
			}
		},
		tools : {
			attr : {
				left : 10,
				top : 10
			},
			pointer : {},
			path : {},
			states : {},
			save : {
				onclick : function(c) {
					alert(c)
				}
			}
		},
		props : {
			attr : {
				top : 10,
				right : 30
			},
			props : {}
		},
		restore : "",
		activeRects : {
			rects : [],
			rectAttr : {
				stroke : "#ff0000",
				"stroke-width" : 2
			}
		},
		historyRects : {
			rects : [],
			pathAttr : {
				path : {
					stroke : "#00ff00"
				},
				arrow : {
					stroke : "#00ff00",
					fill : "#00ff00"
				}
			}
		}
	};
	a.util = {
		isLine : function(g, f, e) {
			var d, c;
			if ((g.x - e.x) == 0) {
				d = 1
			} else {
				d = (g.y - e.y) / (g.x - e.x)
			}
			c = (f.x - e.x) * d + e.y;
			if ((f.y - c) < 10 && (f.y - c) > -10) {
				f.y = c;
				return true
			}
			return false;
		},
		center : function(d, c) {
			return {
				x : (d.x - c.x) / 2 + c.x,
				y : (d.y - c.y) / 2 + c.y
			}
		},
		nextId : (function(obj,type) {
			return function(obj,type) {
				if (obj && obj.props && obj.props.code.value != ''){
					return obj.props.code.value; 
				}else{
					$("#objectIndex").val(parseInt($("#objectIndex").val())+1);
					if (type == 'rect'){
						return 'rect'+$("#objectIndex").val();	
					}else{
						return 'path'+$("#objectIndex").val();
					}
				}
			}
		})(),
		connPoint : function(j, d) {
			var c = d, e = {
				x : j.x + j.width / 2,
				y : j.y + j.height / 2
			};
			var l = (e.y - c.y) / (e.x - c.x);
			l = isNaN(l) ? 0 : l;
			var k = j.height / j.width;
			var h = c.y < e.y ? -1 : 1, f = c.x < e.x ? -1 : 1, g, i;
			if (Math.abs(l) > k && h == -1) {
				g = e.y - j.height / 2;
				i = e.x + h * j.height / 2 / l
			} else {
				if (Math.abs(l) > k && h == 1) {
					g = e.y + j.height / 2;
					i = e.x + h * j.height / 2 / l
				} else {
					if (Math.abs(l) < k && f == -1) {
						g = e.y + f * j.width / 2 * l;
						i = e.x - j.width / 2
					} else {
						if (Math.abs(l) < k && f == 1) {
							g = e.y + j.width / 2 * l;
							i = e.x + j.width / 2
						}
					}
				}
			}
			return {
				x : i,
				y : g
			}
		},
		arrow : function(l, k, d) {
			var g = Math.atan2(l.y - k.y, k.x - l.x) * (180 / Math.PI);
			var h = k.x - d * Math.cos(g * (Math.PI / 180));
			var f = k.y + d * Math.sin(g * (Math.PI / 180));
			var e = h + d * Math.cos((g + 120) * (Math.PI / 180));
			var j = f - d * Math.sin((g + 120) * (Math.PI / 180));
			var c = h + d * Math.cos((g + 240) * (Math.PI / 180));
			var i = f - d * Math.sin((g + 240) * (Math.PI / 180));
			return [ k, {
				x : e,
				y : j
			}, {
				x : c,
				y : i
			} ]
		},
		jsonText:function(q,g,r){
			var i = '{"states":{';
			for ( var c in q) {
				if (q[c]) {
					i += q[c].getId() + ':' + q[c].toJson() + ','
				}
			}
			if (i.substring(i.length - 1, i.length) == ",") {
				i = i.substring(0, i.length - 1)
			}
			i += '},"paths":{';
			for ( var c in g) {
				if (g[c]) {
					i += g[c].getId() + ':' + g[c].toJson() + ','
				}
			}
			if (i.substring(i.length - 1, i.length) == ",") {
				i = i.substring(0, i.length - 1)
			}
			i += '},"props":{"props":{';
			
			var tt = r.restore;
			for (var c in a.config.props.props) {
				if (c == 'index'){
					i += c + ':{"value":"'+ $("#objectIndex").val() + '"},'
				}else{
					i += c + ':{"value":"'+ tt.props.props[c].value + '"},'					
				}
			}
			if (i.substring(i.length - 1, i.length) == ",") {
				i = i.substring(0, i.length - 1)
			}
			i += '}}}';
			return i;
		}
	};
	a.rect = function(p, m) {
		var u = this, g = a.util.nextId(p,'rect'), E = b.extend(true, {},
				a.config.rect, p), C = m, t, e, n, f, x, v;
		t = C.rect(E.attr.x, E.attr.y, E.attr.width, E.attr.height, E.attr.r)
				.hide().attr(E.attr);
		e = C.image(a.config.basePath + E.img.src, E.attr.x + E.img.width / 2,
				E.attr.y + (E.attr.height - E.img.height) / 2, E.img.width,
				E.img.height).hide();
		n = C.text(E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2,
				E.attr.y + a.config.lineHeight / 2, E.name.text).hide().attr(
				E.name);
		f = C.text(
				E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2,
				E.attr.y + (E.attr.height - a.config.lineHeight) / 2
						+ a.config.lineHeight, E.text.text).hide().attr(E.text);
		t.drag(function(r, o) {
			A(r, o)
		}, function() {
			z()
		}, function() {
			l()
		});
		e.drag(function(r, o) {
			A(r, o)
		}, function() {
			z()
		}, function() {
			l()
		});
		n.drag(function(r, o) {
			A(r, o)
		}, function() {
			z()
		}, function() {
			l()
		});
		f.drag(function(r, o) {
			A(r, o)
		}, function() {
			z()
		}, function() {
			l()
		});
		var A = function(F, r) {
			if (!a.config.editable) {
				return
			}
			var o = (x + F);
			var G = (v + r);
			q.x = o - E.margin;
			q.y = G - E.margin;
			B()
		};
		var z = function() {
			x = t.attr("x");
			v = t.attr("y");
			t.attr({
				opacity : 0.5
			});
			e.attr({
				opacity : 0.5
			});
			f.attr({
				opacity : 0.5
			})
		};
		var l = function() {
			t.attr({
				opacity : 1
			});
			e.attr({
				opacity : 1
			});
			f.attr({
				opacity : 1
			})
		};
		var s, i = {}, h = 5, q = {
			x : E.attr.x - E.margin,
			y : E.attr.y - E.margin,
			width : E.attr.width + E.margin * 2,
			height : E.attr.height + E.margin * 2
		};
		s = C.path("M0 0L1 1").hide();
		i.t = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "s-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "t")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "t")
		}, function() {
		});
		i.lt = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "nw-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "lt")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lt")
		}, function() {
		});
		i.l = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "w-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "l")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "l")
		}, function() {
		});
		i.lb = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "sw-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "lb")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lb")
		}, function() {
		});
		i.b = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "s-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "b")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "b")
		}, function() {
		});
		i.rb = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "se-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "rb")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rb")
		}, function() {
		});
		i.r = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "w-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "r")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "r")
		}, function() {
		});
		i.rt = C.rect(0, 0, h, h).attr({
			fill : "#000",
			stroke : "#fff",
			cursor : "ne-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "rt")
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rt")
		}, function() {
		});
		var D = function(F, r, G) {
			if (!a.config.editable) {
				return
			}
			var o = _bx + F, H = _by + r;
			switch (G) {
			case "t":
				q.height += q.y - H;
				q.y = H;
				break;
			case "lt":
				q.width += q.x - o;
				q.height += q.y - H;
				q.x = o;
				q.y = H;
				break;
			case "l":
				q.width += q.x - o;
				q.x = o;
				break;
			case "lb":
				q.height = H - q.y;
				q.width += q.x - o;
				q.x = o;
				break;
			case "b":
				q.height = H - q.y;
				break;
			case "rb":
				q.height = H - q.y;
				q.width = o - q.x;
				break;
			case "r":
				q.width = o - q.x;
				break;
			case "rt":
				q.width = o - q.x;
				q.height += q.y - H;
				q.y = H;
				break
			}
			B()
		};
		var k = function(r, o, F) {
			_bx = r;
			_by = o
		};
		b([ t.node, f.node, n.node, e.node ]).bind(
				"click",
				function() {
					if (!a.config.editable) {
						return
					}
					w();
					var o = b(C).data("mod");
					switch (o) {
					case "pointer":
						break;
					case "path":
						var r = b(C).data("currNode");
						if (r && r.getId() != g
								&& r.getId().substring(0, 4) == "rect") {
							b(C).trigger("addpath", [ r, u ])
						}
						break
					}
					b(C).trigger("click", u);
					b(C).data("currNode", u);
					currObject = u;
					currentNode = u;
					return false;
				});
		var j = function(o, r) {
			if (!a.config.editable) {
				return
			}
			if (r.getId() == g) {
				/*
				b(C).trigger("showprops", [ E.props, r ])
				*/
			} else {
				d()
			}
		};
		b(C).bind("click", j);
		var c = function(o, F, r) {
			if (r.getId() == g) {
				f.attr({
					text : F
				})
			}
		};
		b(C).bind("textchange", c);
		function y() {
			return "M" + q.x + " " + q.y + "L" + q.x + " " + (q.y + q.height)
					+ "L" + (q.x + q.width) + " " + (q.y + q.height) + "L"
					+ (q.x + q.width) + " " + q.y + "L" + q.x + " " + q.y
		}
		function w() {
			s.show();
			for ( var o in i) {
				i[o].show()
			}
		}
		function d() {
			s.hide();
			for ( var o in i) {
				i[o].hide()
			}
		}
		function B() {
			var F = q.x + E.margin, r = q.y + E.margin, G = q.width - E.margin
					* 2, o = q.height - E.margin * 2;
			t.attr({
				x : F,
				y : r,
				width : G,
				height : o
			});
			switch (E.showType) {
			case "image":
				e.attr({
					x : F + (G - E.img.width) / 2,
					y : r + (o - E.img.height) / 2
				}).show();
				break;
			case "text":
				t.show();
				f.attr({
					x : F + G / 2,
					y : r + o / 2
				}).show();
				break;
			case "image&text":
				t.show();
				n.attr({
					x : F + E.img.width + (G - E.img.width) / 2,
					y : r + a.config.lineHeight / 2
				}).show();
				f.attr({
					x : F + E.img.width + (G - E.img.width) / 2,
					y : r + (o - a.config.lineHeight) / 2 + a.config.lineHeight
				}).show();
				e.attr({
					x : F + E.img.width / 2,
					y : r + (o - E.img.height) / 2
				}).show();
				break
			}
			i.t.attr({
				x : q.x + q.width / 2 - h / 2,
				y : q.y - h / 2
			});
			i.lt.attr({
				x : q.x - h / 2,
				y : q.y - h / 2
			});
			i.l.attr({
				x : q.x - h / 2,
				y : q.y - h / 2 + q.height / 2
			});
			i.lb.attr({
				x : q.x - h / 2,
				y : q.y - h / 2 + q.height
			});
			i.b.attr({
				x : q.x - h / 2 + q.width / 2,
				y : q.y - h / 2 + q.height
			});
			i.rb.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2 + q.height
			});
			i.r.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2 + q.height / 2
			});
			i.rt.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2
			});
			s.attr({
				path : y()
			});
			b(C).trigger("rectresize", u)
		}
		this.toJson = function() {
			var r = '{"type":"'+ E.type + '","text":{"text":"' + f.attr("text")
					+ '"}, "attr":{"x":' + Math.round(t.attr("x")) + ',"y":'
					+ Math.round(t.attr("y")) + ', "width":'
					+ Math.round(t.attr("width")) + ', "height":'
					+ Math.round(t.attr("height")) + '},"props":{';
			for ( var o in E.props) {
				r += '"' + o + '"' + ':{"value":"' + E.props[o].value + '"},'
			}
			if (r.substring(r.length - 1, r.length) == ",") {
				r = r.substring(0, r.length - 1)
			}
			r += '}}';
			return r
		};
		this.restore = function(o) {
			var r = o;
			E = b.extend(true, E, o);
			f.attr({
				text : r.text.text
			});
			B();
		};
		this.moveY = function(y){
			A(0, y);
			z();
			l();
		};
		this.moveX = function(x){
			A(x, 0);
			z();
			l();
		};
		this.getBBox = function() {
			return q
		};
		this.getId = function() {
			return g
		};
		this.remove = function() {
			t.remove();
			f.remove();
			n.remove();
			e.remove();
			s.remove();
			for ( var o in i) {
				i[o].remove()
			}
		};
		this.text = function() {
			return f.attr("text")
		};		
		this.setText = function(text) {
			f.attr("text",text);
		};		
		this.attr = function(o) {
			if (o) {
				t.attr(o)
			}
		};
		B()
	};
	a.path = function(q, n, u, e) {
		var v = this, z = n, B = b.extend(true, {}, a.config.path), i, t, f, h = B.textPos, y, w, k = u, s = e, g = a.util.nextId(q,'path'), x;
		function p(G, H, D, L) {
			var F = this, M = G, r, o = D, O = L, K, I, N = H;
			switch (M) {
			case "from":
				r = z.rect(H.x - B.attr.fromDot.width / 2,
						H.y - B.attr.fromDot.height / 2, B.attr.fromDot.width,
						B.attr.fromDot.height).attr(B.attr.fromDot);
				break;
			case "big":
				r = z.rect(H.x - B.attr.bigDot.width / 2,
						H.y - B.attr.bigDot.height / 2, B.attr.bigDot.width,
						B.attr.bigDot.height).attr(B.attr.bigDot);
				break;
			case "small":
				r = z.rect(H.x - B.attr.smallDot.width / 2,
						H.y - B.attr.smallDot.height / 2,
						B.attr.smallDot.width, B.attr.smallDot.height).attr(
						B.attr.smallDot);
				break;
			case "to":
				r = z.rect(H.x - B.attr.toDot.width / 2,
						H.y - B.attr.toDot.height / 2, B.attr.toDot.width,
						B.attr.toDot.height).attr(B.attr.toDot);
				break
			}
			if (r && (M == "big" || M == "small")) {
				r.drag(function(Q, P) {
					C(Q, P)
				}, function() {
					J()
				}, function() {
					E()
				});
				var C = function(R, Q) {
					var P = (K + R), S = (I + Q);
					F.moveTo(P, S)
				};
				var J = function() {
					if (M == "big") {
						K = r.attr("x") + B.attr.bigDot.width / 2;
						I = r.attr("y") + B.attr.bigDot.height / 2
					}
					if (M == "small") {
						K = r.attr("x") + B.attr.smallDot.width / 2;
						I = r.attr("y") + B.attr.smallDot.height / 2
					}
				};
				var E = function() {
				}
			}
			this.type = function(P) {
				if (P) {
					M = P
				} else {
					return M
				}
			};
			this.node = function(P) {
				if (P) {
					r = P
				} else {
					return r
				}
			};
			this.left = function(P) {
				if (P) {
					o = P
				} else {
					return o
				}
			};
			this.right = function(P) {
				if (P) {
					O = P
				} else {
					return O
				}
			};
			this.remove = function() {
				o = null;
				O = null;
				r.remove()
			};
			this.pos = function(P) {
				if (P) {
					N = P;
					r.attr({
						x : N.x - r.attr("width") / 2,
						y : N.y - r.attr("height") / 2
					});
					return this
				} else {
					return N
				}
			};
			this.moveTo = function(Q, T) {
				this.pos({
					x : Q,
					y : T
				});
				switch (M) {
				case "from":
					if (O && O.right() && O.right().type() == "to") {
						O.right().pos(a.util.connPoint(s.getBBox(), N))
					}
					if (O && O.right()) {
						O.pos(a.util.center(N, O.right().pos()))
					}
					break;
				case "big":
					if (O && O.right() && O.right().type() == "to") {
						O.right().pos(a.util.connPoint(s.getBBox(), N))
					}
					if (o && o.left() && o.left().type() == "from") {
						o.left().pos(a.util.connPoint(k.getBBox(), N))
					}
					if (O && O.right()) {
						O.pos(a.util.center(N, O.right().pos()))
					}
					if (o && o.left()) {
						o.pos(a.util.center(N, o.left().pos()))
					}
					var S = {
						x : N.x,
						y : N.y
					};
					if (a.util.isLine(o.left().pos(), S, O.right().pos())) {
						M = "small";
						r.attr(B.attr.smallDot);
						this.pos(S);
						var P = o;
						o.left().right(o.right());
						o = o.left();
						P.remove();
						var R = O;
						O.right().left(O.left());
						O = O.right();
						R.remove()
					}
					break;
				case "small":
					if (o && O && !a.util.isLine(o.pos(), {
						x : N.x,
						y : N.y
					}, O.pos())) {
						M = "big";
						r.attr(B.attr.bigDot);
						var P = new p("small", a.util.center(o.pos(), N), o, o
								.right());
						o.right(P);
						o = P;
						var R = new p("small", a.util.center(O.pos(), N), O
								.left(), O);
						O.left(R);
						O = R
					}
					break;
				case "to":
					if (o && o.left() && o.left().type() == "from") {
						o.left().pos(a.util.connPoint(k.getBBox(), N))
					}
					if (o && o.left()) {
						o.pos(a.util.center(N, o.left().pos()))
					}
					break
				}
				m()
			}
		}
		function j() {
			var D, C, E = k.getBBox(), F = s.getBBox(), r, o;
			r = a.util.connPoint(E, {
				x : F.x + F.width / 2,
				y : F.y + F.height / 2
			});
			o = a.util.connPoint(F, r);
			D = new p("from", r, null, new p("small", {
				x : (r.x + o.x) / 2,
				y : (r.y + o.y) / 2
			}));
			D.right().left(D);
			C = new p("to", o, D.right(), null);
			D.right().right(C);
			this.toPathString = function() {
				if (!D) {
					return ""
				}
				var J = D, I = "M" + J.pos().x + " " + J.pos().y, H = "";
				while (J.right()) {
					J = J.right();
					I += "L" + J.pos().x + " " + J.pos().y
				}
				var G = a.util.arrow(J.left().pos(), J.pos(),
						B.attr.arrow.radius);
				H = "M" + G[0].x + " " + G[0].y + "L" + G[1].x + " " + G[1].y
						+ "L" + G[2].x + " " + G[2].y + "z";
				return [ I, H ]
			};
			this.toJson = function() {
				var G = "[", H = D;
				while (H) {
					if (H.type() == "big") {
						G += '{"x":' + Math.round(H.pos().x) + ',"y":'
								+ Math.round(H.pos().y) + '},'
					}
					H = H.right()
				}
				if (G.substring(G.length - 1, G.length) == ",") {
					G = G.substring(0, G.length - 1)
				}
				G += ']';
				return G
			};
			this.restore = function(H) {
				var I = H, J = D.right();
				for ( var G = 0; G < I.length; G++) {
					J.moveTo(I[G].x, I[G].y);
					J.moveTo(I[G].x, I[G].y);
					J = J.right()
				}
				this.hide()
			};
			this.fromDot = function() {
				return D
			};
			this.toDot = function() {
				return C
			};
			this.midDot = function() {
				var H = D.right(), G = D.right().right();
				while (G.right() && G.right().right()) {
					G = G.right().right();
					H = H.right()
				}
				return H
			};
			this.show = function() {
				var G = D;
				while (G) {
					G.node().show();
					G = G.right()
				}
			};
			this.hide = function() {
				var G = D;
				while (G) {
					G.node().hide();
					G = G.right()
				}
			};
			this.remove = function() {
				var G = D;
				while (G) {
					if (G.right()) {
						G = G.right();
						G.left().remove()
					} else {
						G.remove();
						G = null
					}
				}
			}
		}
		B = b.extend(true, B, q);
		i = z.path(B.attr.path.path).attr(B.attr.path);
		t = z.path(B.attr.arrow.path).attr(B.attr.arrow);
		x = new j();
		x.hide();
		f = z.text(0, 0, B.text.text).attr(B.text).attr(
				{
					text : B.text.text.replace("{from}", k.text()).replace(
							"{to}", s.text())
				});
		f.drag(function(r, o) {
			if (!a.config.editable) {
				return
			}
			f.attr({
				x : y + r,
				y : w + o
			})
		}, function() {
			y = f.attr("x");
			w = f.attr("y")
		}, function() {
			var o = x.midDot().pos();
			h = {
				x : f.attr("x") - o.x,
				y : f.attr("y") - o.y
			}
		});
		m();
		b([ i.node, t.node ]).bind("click", function() {
			if (!a.config.editable) {
				return
			}
			b(z).trigger("click", v);
			b(z).data("currNode", v);
			currObject = v;
			return false;
		});
		var l = function(r, C) {
			if (!a.config.editable) {
				return
			}
			if (C && C.getId() == g) {
				x.show();
				/*
				b(z).trigger("showprops", [ B.props, v ])
				*/
			} else {
				x.hide()
			}
			var o = b(z).data("mod");
			switch (o) {
			case "pointer":
				break;
			case "path":
				break
			}
		};
		b(z).bind("click", l);
		var A = function(o, r) {
			if (!a.config.editable) {
				return
			}
//			alert("r.getId() is " + r.getId());
//			alert("k.getId() is " + k.getId());
//			alert("s.getId() is " + s.getId());
//			alert("v.getId() is " + v.getId());
			if (r && (r.getId() == k.getId() || r.getId() == s.getId())) {
				b(z).trigger("removepath", v)
				//g[v.getId()] = null;
				//v.remove()		
			}
		};
		b(z).bind("removerect", A);
		var d = function(C, D) {
			if (!a.config.editable) {
				return
			}
			if (k && k.getId() == D.getId()) {
				var o;
				if (x.fromDot().right().right().type() == "to") {
					o = {
						x : s.getBBox().x + s.getBBox().width / 2,
						y : s.getBBox().y + s.getBBox().height / 2
					}
				} else {
					o = x.fromDot().right().right().pos()
				}
				var r = a.util.connPoint(k.getBBox(), o);
				x.fromDot().moveTo(r.x, r.y);
				m()
			}
			if (s && s.getId() == D.getId()) {
				var o;
				if (x.toDot().left().left().type() == "from") {
					o = {
						x : k.getBBox().x + k.getBBox().width / 2,
						y : k.getBBox().y + k.getBBox().height / 2
					}
				} else {
					o = x.toDot().left().left().pos()
				}
				var r = a.util.connPoint(s.getBBox(), o);
				x.toDot().moveTo(r.x, r.y);
				m()
			}
		};
		b(z).bind("rectresize", d);
		var c = function(r, o, C) {
			if (C.getId() == g) {
				f.attr({
					text : o
				})
			}
		};
		b(z).bind("textchange", c);
		this.from = function() {
			return k
		};
		this.to = function() {
			return s
		};
		this.toJson = function() {
			var r = '{"from":"' + k.getId() + '","to":"' + s.getId() + '","dots":'
					+ x.toJson() + ',"text":{"text":"' + f.attr("text")
					+ '"},"textPos":{"x":' + Math.round(h.x) + ',"y":'
					+ Math.round(h.y) + '}, "props":{';
			for ( var o in B.props) {
				r += '"'+ o + '"' + ':{"value":"' + B.props[o].value + '"},'
			}
			if (r.substring(r.length - 1, r.length) == ',') {
				r = r.substring(0, r.length - 1)
			}
			r += '}}';
			return r
		};
		this.restore = function(o) {
			var r = o;
			B = b.extend(true, B, o);
			x.restore(r.dots)
		};
		this.remove = function() {
			x.remove();
			i.remove();
			t.remove();
			f.remove();
			try {
				b(z).unbind("click", l)
			} catch (o) {
			}
			try {
				b(z).unbind("removerect", A)
			} catch (o) {
			}
			try {
				b(z).unbind("rectresize", d)
			} catch (o) {
			}
			try {
				b(z).unbind("textchange", c)
			} catch (o) {
			}
		};
		function m() {
			var r = x.toPathString(), o = x.midDot().pos();
			i.attr({
				path : r[0]
			});
			t.attr({
				path : r[1]
			});
			f.attr({
				x : o.x + h.x,
				y : o.y + h.y
			})
		}
		this.getId = function() {
			return g
		};
		this.text = function() {
			return f.attr("text")
		};
		this.setText = function(text) {
			f.attr("text",text);
		};		
		this.code = function() {
			return f.attr("code")
		};
		this.id = function() {
			return f.attr("id")
		};		
		this.attr = function(o) {
			if (o && o.path) {
				i.attr(o.path)
			}
			if (o && o.arrow) {
				t.attr(o.arrow)
			}
		}
	};
	a.props = function(h, f) {
		var j = this, c = b("#myflow_props").hide().draggable({
			handle : "#myflow_props_handle"
		}).resizable().css(a.config.props.attr).bind("click", function() {
			return false
		}), e = c.find("table"), g = f, i;
		var d = function(n, m, o) {
			if (i && i.getId() == o.getId()) {
				return
			}
			i = o;
			b(e).find(".editor").each(function() {
				var k = b(this).data("editor");
				if (k) {
					k.destroy()
				}
			});
			e.empty();
			c.show();
			for ( var l in m) {
				//alert('l is ' + l);
				e.append("<tr><th>" + m[l].label + '</th><td><div id="p' + l
						+ '" class="editor"></div></td></tr>');
				if (m[l].editor) {
					m[l].editor().init(m, l, "p" + l, o, g)
				}
			}
		};
		b(g).bind("showprops", d)
	};
	/*
	a.editors = {
		textEditor : function() {
			var d, e, c, g, f;
			this.init = function(i, h, m, l, j) {
				d = i;
				e = h;
				c = m;
				g = l;
				f = j;
				b('<input  style="width:100%;"/>').val(g.text()).change(
						function() {
							i[e].value = b(this).val();
							b(f).trigger("textchange", [ b(this).val(), g ])
						}).appendTo("#" + c);
				b("#" + c).data("editor", this)
			};
			this.destroy = function() {
				b("#" + c + " input").each(function() {
					d[e].value = b(this).val();
					b(f).trigger("textchange", [ b(this).val(), g ])
				})
			}
		}
	};
	*/
	a.init = function(x, r) {
		b.extend(true, a.config, r);
		var ratio = 1.5;
		if (!a.config.editable){
			ratio = 1.7;
		}
		//alert("ratio is " + ratio);
		var v = b(window).width(), e = b(window).height(), y = Raphael(x,
				v * ratio, e * ratio), q = {}, g = {};
		b(document).keydown(function(i) {
			if (!a.config.editable) {
				return
			}
			if (i.keyCode == 46) {
				var j = b(y).data("currNode");
				if (j) {
					if (j.getId().substring(0, 4) == "rect") {
						$("#evtObjec").val('rect');
						b(y).trigger("removerect", j)
					} else {
						if (j.getId().substring(0, 4) == "path") {
							$("#evtObjec").val('path');
							b(y).trigger("removepath", j)
						}
					}
					b(y).removeData("currNode");
					currObject = null;
					currentNode = null;
				}
			}
		});
		b(document).click(function() {
			b(y).data("currNode", null);
			currObject = null;
			currentNode = null;
			b(y).trigger("click", {
				getId : function() {
					return "00000000"
				}
			});
			/*
			b(y).trigger("showprops", [ a.config.props.props, {
				getId : function() {
					return "00000000"
				}
			} ])
			*/
		});
		b(document).dblclick(function() {
			if (!a.config.editable) {
				return
			}		
			var temp = b(y).data("currNode");
			//alert(temp);
			if (temp){
				//alert(temp.toJson());
				var jsonObj = $.parseJSON(temp.toJson());
				if (jsonObj.hasOwnProperty("type")){
					currentModel = temp;
					var objId = jsonObj.props.key.value;
					var objType = jsonObj.type;
					showActivityBox(objType,objId);
				}else{
					currentLine = temp;
					var objId = jsonObj.props.key.value;
					showTransitionBox(objId);
				}				
			}
		});		
		var w = function(c, i) {
			if (!a.config.editable) {
				return
			}
			if (i.getId().substring(0, 4) == "rect") {
				//alert("removerect");
				//alert(i.getId());
				//alert(i.toJson());
				var actObj = $.parseJSON(i.toJson());
				//alert(actObj.type)
				if (actObj.type == 'start'){
					alert('不能删除开始节点！');
					return;
				}
				else if (actObj.type == 'end'){
					alert('不能删除结束节点！');
					return;					
				}				
				
				q[i.getId()] = null;
				i.remove();
				
				var tt = r.restore;
				var processId = tt.props.props['key'].value;
				var datas ="processId="+processId;
				$("#tempJson").val(i.toJson());
				$("#processJson").val(a.util.jsonText(q, g, r));
				postRequest('form1',{actionType:'deleteActivity',data:datas,onComplete:function(responseText){
					if ("success" != responseText){
						alert("出错啦，请联系管理员！");
					}
				}});
			} else {
				if (i.getId().substring(0, 4) == "path") {
//					alert("removepath");
//					alert(i.getId());
//					alert(i.toJson());
					
					if ($("#evtObjec").val() == 'rect'){
						g[i.getId()] = null;
						i.remove();
					}else{
						g[i.getId()] = null;
						i.remove();
						
						var tt = r.restore;
						var processId = tt.props.props['key'].value;
						var datas ="processId="+processId;
						$("#tempJson").val(i.toJson());
						$("#processJson").val(a.util.jsonText(q, g, r));
						postRequest('form1',{actionType:'deleteTransition',data:datas,onComplete:function(responseText){
							if ("success" != responseText){					
								alert("出错啦，请联系管理员！");
							}
						}});						
					}
				}
			}
		};
		b(y).bind("removepath", w);
		b(y).bind("removerect", w);
		b(y).bind(
				"addrect",
				function(j, c, k) {
					if (c == 'start'){
						alert('开始节点已默认创建，不能再创建！');
						return;
					}
					if (c == 'end'){
						alert('开始节点已默认创建，不能再创建！');
						return;
					}
					
					var i = new a.rect(b.extend(true, {},
							a.config.tools.states[c], k), y);
					q[i.getId()] = i;
					
					var tt = r.restore;
					var processId = tt.props.props['key'].value;
					var activityType = c;
					var activityCode = i.getId();
					$("#tempJson").val(i.toJson());
					var datas ="processId="+processId+"&activityType="+activityType+"&activityCode="+activityCode;
					postRequest('form1',{actionType:'createActivity',data:datas,onComplete:function(responseText){
						var temp = $.parseJSON(responseText);
						i.restore(temp);
						q[i.getId()] = i;
						
						var jsonText = a.util.jsonText(q, g, r);
						$("#processJson").val(jsonText);
						postRequest('form1',{actionType:'saveProccessDefine',onComplete:function(responseText){
							
						}});
						
					}});
				});
		var f = function(i, k, j) {
			var c = new a.path({}, y, k, j);
			g[c.getId()] = c;
			//alert('addpath');
			//alert('k id is ' + k.getId());
			//alert('j id is ' + j.getId());
			
			var tt = r.restore;
			var processId = tt.props.props['key'].value;
			var transitionCode = c.getId();
			var fromActivityCode = k.getId();
			var toActivityCode = j.getId();
			$("#tempJson").val(c.toJson());
			
			var datas ="processId="+processId+"&transitionCode="+transitionCode+"&fromActivityCode="+fromActivityCode+"&toActivityCode="+toActivityCode;
			postRequest('form1',{actionType:'createTransition',data:datas,onComplete:function(responseText){
				var temp = $.parseJSON(responseText);
				c.restore(temp);
				g[c.getId()] = c;
				
				var jsonText = a.util.jsonText(q, g, r);
				$("#processJson").val(jsonText);
				postRequest('form1',{actionType:'saveProccessDefine',onComplete:function(responseText){
					
				}});
			}});
			
		};
		b(y).bind("addpath", f);
		b(y).data("mod", "point");
		if (a.config.editable) {
			b("#myflow_tools").draggable({
				handle : "#myflow_tools_handle"
			}).css(a.config.tools.attr);
			b("#myflow_tools .node").hover(function() {
				b(this).addClass("mover")
			}, function() {
				b(this).removeClass("mover")
			});
			b("#myflow_tools .selectable").click(function() {
				b(".selected").removeClass("selected");
				b(this).addClass("selected");
				b(y).data("mod", this.id)
			});
			b("#myflow_tools .state").each(function() {
				b(this).draggable({
					helper : "clone"
				})
			});
			b(x).droppable({
				accept : ".state",
				drop : function(c, i) {
					b(y).trigger("addrect", [ i.helper.attr("type"), {
						attr : {
							x : i.helper.offset().left,
							y : i.helper.offset().top
						}
					} ])
				}
			});
			
			b("#save").click(
				function() {
					var i = a.util.jsonText(q,g,r);
					a.config.tools.save.onclick(i)
				});
			b("#prop").click(
				function() {
					setupRequest();
				});
			new a.props({}, y)
		}
		if (r.restore) {
			var B = r.restore;
			var z = {};
			if (B.states) {
				for ( var s in B.states) {
					var d = new a.rect(b.extend(true, {},
							a.config.tools.states[B.states[s].type],
							B.states[s]), y);
					d.restore(B.states[s]);
					z[s] = d;
					q[d.getId()] = d
				}
			}
			if (B.paths) {
				for ( var s in B.paths) {
					var n = new a.path(b.extend(true, {}, a.config.tools.path,
							B.paths[s]), y, z[B.paths[s].from],
							z[B.paths[s].to]);
					n.restore(B.paths[s]);
					g[n.getId()] = n
				}
			}
		}
		var A = a.config.historyRects, l = a.config.activeRects;
		if (A.rects.length || l.rects.length) {
			var m = {}, z = {};
			for ( var h in g) {
				if (!z[g[h].from().getId()]) {
					z[g[h].from().getId()] = {
						rect : g[h].from(),
						paths : {}
					}
				}
				z[g[h].from().getId()].paths[g[h].getId()] = g[h];
				if (!z[g[h].to().getId()]) {
					z[g[h].to().getId()] = {
						rect : g[h].to(),
						paths : {}
					}
				}
			}
			for ( var u = 0; u < A.rects.length; u++) {
				if (z[A.rects[u].code]) {
					z[A.rects[u].code].rect.attr(A.rectAttr)
				}
				for ( var t = 0; t < A.rects[u].paths.length; t++) {
					if (z[A.rects[u].code].paths[A.rects[u].paths[t]]) {
						z[A.rects[u].code].paths[A.rects[u].paths[t]]
								.attr(A.pathAttr)
					}
				}
			}
			for ( var u = 0; u < l.rects.length; u++) {
				if (z[l.rects[u].code]) {
					z[l.rects[u].code].rect.attr(l.rectAttr)
				}
				for ( var t = 0; t < l.rects[u].paths.length; t++) {
					if (z[l.rects[u].code].paths[l.rects[u].paths[t]]) {
						z[l.rects[u].code].paths[l.rects[u].paths[t]]
								.attr(l.pathAttr)
					}
				}
			}
		}
	};
	b.fn.myflow = function(c) {
		return this.each(function() {
			a.init(this, c)
		})
	};
	b.myflow = a
})(jQuery);